<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
  //   Boolean|Number|String 类型会自动转换成对应的原始值。
  //   undefined、任意函数以及 symbol，会被忽略（出现在非数组对象的属性值中时），或者被转换成 null（出现在数组中时）。
  //   不可枚举的属性会被忽略
  //   如果一个对象的属性值通过某种间接的方式指回该对象本身，即循环引用，属性也会被忽略。

  function jsonStringify(obj) {
    let type = typeof obj;
    if (type !== "object" || type === null) {
      if (/string|undefined|function/.test(type)) {
        obj = '"' + obj + '"';
      }
      return String(obj)
    } else {
      let json = [];
      // typeof []也是object 继续判断是否是数组
      arr = (obj && obj.constructor === Array);
      // 遍历对象
      for (let k in obj) {
        let v = obj[k];
        let type = typeof v;
        if (/string|undefined|function/.test(type)) {
          v = '"' + v + '"';
        } else if (type === "object") {
          //判断如果是object继续递归
          v = jsonStringify(type);
        }
        json.push((arr ? "" : '"'+ k + '":')+String(v))
      }
     return (arr ? "[" : "{") + String(json)+(arr ? "]" : "}")
    }
  }

  console.log(jsonStringify(2))
  console.log(jsonStringify({x: 5}))
  // "{"x":5}"
    console.log(jsonStringify([1, "false", false])) // "[1,"false",false]"
    console.log(jsonStringify({b: undefined}))

</script>
</body>
</html>
